/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.cef.spi.entity.info.propertyinfo;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.inspur.edp.cef.api.manager.serialize.CefSerializeContext;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.spi.entity.info.EnumValueInfo;
import com.inspur.edp.cef.spi.jsonser.util.SerializerUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class EnumPropertyInfo extends BasePropertyInfo {

    private Map<String, EnumValueInfo> enumValueInfos = new HashMap<>();
    private Map<Integer ,EnumValueInfo> indexEnumValueInfos=new HashMap<>();
    private Class enumType;
    private EnumPropertyRepoType repoType=EnumPropertyRepoType.Code;

    public EnumPropertyInfo(){

    }

    public EnumPropertyInfo(EnumPropertyRepoType repoType)
    {
        this.repoType = repoType;
    }
//    public EnumPropertyInfo(Map<String,EnumValueInfo> enumValueInfos) {
//        this.enumValueInfos = enumValueInfos;
//    }

    public final  EnumPropertyRepoType getRepoType()
    {return  repoType;}

    public EnumValueInfo getEnumValueInfo(String key) {
        if (enumValueInfos == null)
            throw new RuntimeException("");
        return enumValueInfos.get(key);
    }

    public EnumValueInfo getEnumValueInfo(Integer index)
    {
        for(Map.Entry<String,EnumValueInfo> item:enumValueInfos.entrySet())
        {
            if(item.getValue().getIndex().equals(index))
                return item.getValue();
        }
        return null;
    }

    public EnumValueInfo getStringIndexEnumValueInfo(String stringIndex)
    {
        for(Map.Entry<String,EnumValueInfo> item:enumValueInfos.entrySet())
        {
            if(item.getValue().getStringIndex().equals(stringIndex))
                return item.getValue();
        }
        return null;
    }

    public void addEnumValueInfo(String displayValueKey, String enumCode, String defaultName, String stringIndex, Integer index) {
        enumValueInfos.put(enumCode, new EnumValueInfo(displayValueKey, enumCode, defaultName, stringIndex, index));
    }

    public void addEnumValueInfo(String displayValueKey, String enumCode, String defaultName, String stringIndex, Integer index, Boolean enumItemDisabled) {
        enumValueInfos.put(enumCode, new EnumValueInfo(displayValueKey, enumCode, defaultName, stringIndex, index,enumItemDisabled));
    }

    public Object getEnumValueFromDac(Object value)
    {
      if (value == null || value.toString().equals(""))     return null;
      switch (repoType)
      {
        case Code:
        case Index:
          Integer integer=Integer.valueOf(value.toString());
          return Enum.valueOf(getEnumType(),getEnumValueInfo(integer).getEnumCode());
        case StringIndex:
            EnumValueInfo enumIndex =getStringIndexEnumValueInfo(value.toString());
            if(enumIndex==null)
                throw new RuntimeException("数据库中的值"+value.toString()+"不在枚举列表中");
          return  Enum.valueOf(getEnumType(),getStringIndexEnumValueInfo(value.toString()).getEnumCode());
          default:
            throw new RuntimeException("未识别的枚举持久化类型："+repoType);
      }
    }

    public List<EnumValueInfo> getEnumValueInfos() {
        List<EnumValueInfo> list =new ArrayList<>();
        for(EnumValueInfo info:enumValueInfos.values())
            list.add(info);
        return list;
//        return (List<EnumValueInfo>) enumValueInfos.values();
    }

    public Class getEnumType() {
        return enumType;
    }

    public void setEnumType(Class enumType) {
        this.enumType = enumType;
    }

    @Override
    public void write(JsonGenerator writer, String propertyName, Object value, SerializerProvider serializer, CefSerializeContext serContext) {
        SerializerUtil.writeEnum(writer, value, propertyName, serializer);
    }

    @Override
    public void writeChange(JsonGenerator writer, String propertyName, Object value, SerializerProvider serializer, CefSerializeContext serContext) {
        SerializerUtil.writeEnum(writer, value, propertyName, serializer);
    }

    @Override
    public Object read(JsonParser reader, String propertyName, DeserializationContext serializer, CefSerializeContext serContext) {
        return SerializerUtil.readEnum(reader, enumType);
    }

    @Override
    public Object read(JsonNode node, String propertyName, CefSerializeContext serContext) {
        return SerializerUtil.readEnum(node, enumType);
    }

    @Override
    public Object readChange(JsonParser reader, String propertyName, DeserializationContext serializer, CefSerializeContext serContext) {
        return SerializerUtil.readEnum(reader, enumType);
    }

    @Override
    public Object readChange(JsonNode node, String propertyName, CefSerializeContext serContext) {
        return SerializerUtil.readEnum(node, enumType);
    }

    @Override
    public void setValue(Object data, String propertyName, Object value, CefSerializeContext serContext) {

    }

    @Override
    public Object createValue() {
        return null;
    }

    private String getDefaultEnumCode()
    {
        for(String str:enumValueInfos.keySet())
        {
            return str;
        }
        return "";
    }

    public Object createAssociationDefaultValue() {
        Class<Enum> enumClass = (Class<Enum>) enumType;
        return Enum.valueOf(enumClass, getDefaultEnumCode());
    }

    @Override
    public String getPropValue(Object value) {
        if(value==null){
            return "";
        }
        return "\""+String.valueOf(value)+"\"";
    }
}
